# -*- coding: utf-8 -*-
__author__ = 'BuddyHolly'

import os
import sys
import shutil
import hashlib

from flask import render_template, request, flash, current_app, send_from_directory, after_this_request, g
from flask_login import login_required, current_user

import formVerify
from . import main
from app.src.pptprocess import replacePic, withdrawPic
from app.src.imgsave import savePic, infoPic
from app.src.imgprocess import genWm, enPic, dePic, zipPic, comWm

reload(sys)
sys.setdefaultencoding('utf8')


@main.before_request
def before_request():
    g.url = 'index.html'


# 主视图
@main.route('/')
def index():
    return render_template('index.html')


# 异常处理
@main.errorhandler(404)
def errors(error):
    return render_template('404.html')


# ============================================================================
# 以下为主要功能路由
# 都用login_required，formVerify.error_decorator两个装饰器修饰，表示登录可用及异常处理
# ============================================================================

# PPT水印添加——生成盲水印
@main.route('/genwm_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def genwm_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/genwm_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 ppt:PPT文件 wm_text：水印字样
        ppt = request.files['ppt']
        wm_text = request.form.get('wm_text')

        # 验证水印内容
        if len(wm_text) == 0:
            flash("水印内容不能为空！")
            return render_template('main/genwm_add.html')

        # 验证获取的ppt文件
        if ppt and formVerify.allowed_file_ppt(ppt.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            hash_name = hashlib.md5(SECRET_KEY + ppt.filename + current_user.email).hexdigest()
            # 保存ppt
            ppt_name = hash_name + ".pptx"
            ppt_path_name = os.path.join(os.getcwd(), 'temp/ppt/', ppt_name)
            ppt.save(ppt_path_name)
            g.file_list.append(ppt_path_name)

            # 保存ppt中所有图片
            pic_path = os.path.join(os.getcwd(), 'temp/picture/', hash_name)
            if not os.path.exists(pic_path):
                os.mkdir(pic_path)
                g.path_list.append(pic_path)
            name_list = savePic.save_pic(ppt_path_name, pic_path)

            # 生成水印
            wm_path = os.path.join(os.getcwd(), 'temp/wm')
            wm_file = genWm.gen_wm(wm_text, hash_name, wm_path)
            g.file_list.append(wm_file)

            # 添加盲水印
            for name in name_list:
                name_path = os.path.join(pic_path, name)
                enPic.en_pic(name_path, wm_file)

            # 还原图片
            infos = infoPic.InfoPic(ppt_path_name)
            replacePic.replace_pic(ppt_path_name, pic_path, infos.get_info())

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(wm_file)
                    shutil.rmtree(pic_path)
                    os.remove(ppt_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的PPT文件下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/ppt'), ppt_name, as_attachment=True)
        else:
            flash("您导入的不是pptx文件！")
            return render_template('main/genwm_add.html')
    return render_template('main/genwm_add.html')


# PPT水印添加——生成传统水印
@main.route('/comwm_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def comwm_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/comwm_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 ppt:PPT文件 wm_text：水印字样
        ppt = request.files['ppt']
        wm_text = request.form.get('wm_text')

        # 验证水印内容
        if len(wm_text) == 0:
            flash("水印内容不能为空！")
            return render_template('main/comwm_add.html')

        # 验证获取的ppt文件
        if ppt and formVerify.allowed_file_ppt(ppt.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            hash_name = hashlib.md5(SECRET_KEY + ppt.filename + current_user.email).hexdigest()
            # 保存ppt
            ppt_name = hash_name + ".pptx"
            ppt_path_name = os.path.join(os.getcwd(), 'temp/ppt/', ppt_name)
            ppt.save(ppt_path_name)
            g.file_list.append(ppt_path_name)

            # 保存ppt中所有图片
            pic_path = os.path.join(os.getcwd(), 'temp/picture/', hash_name)
            if not os.path.exists(pic_path):
                os.mkdir(pic_path)
                g.path_list.append(pic_path)
            name_list = savePic.save_pic(ppt_path_name, pic_path)

            # 添加传统水印(com_wm中包含生成传统水印内容)
            for name in name_list:
                name_path = os.path.join(pic_path, name)
                comWm.com_wm(name_path, wm_text)

            # 还原图片
            infos = infoPic.InfoPic(ppt_path_name)
            replacePic.replace_pic(ppt_path_name, pic_path, infos.get_info())

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    shutil.rmtree(pic_path)
                    os.remove(ppt_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的PPT文件下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/ppt'), ppt_name, as_attachment=True)
        else:
            flash("您导入的不是pptx文件！")
            return render_template('main/comwm_add.html')
    return render_template('main/comwm_add.html')


# PPT水印添加——上传水印图
@main.route('/selfwm_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def selfwm_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/selfwm_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 ppt:PPT文件 file_wm：水印图
        ppt = request.files['ppt']
        file_wm = request.files['file_wm']

        # 验证获取的ppt文件及水印图
        if ppt and file_wm and formVerify.allowed_file_ppt(ppt.filename) and formVerify.allowed_file_png(
                file_wm.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            hash_name = hashlib.md5(SECRET_KEY + ppt.filename + current_user.email).hexdigest()
            # 保存ppt
            ppt_name = hash_name + ".pptx"
            ppt_path_name = os.path.join(os.getcwd(), 'temp/ppt/', ppt_name)
            ppt.save(ppt_path_name)
            g.file_list.append(ppt_path_name)
            # 保存水印图
            wm_path = os.path.join(os.getcwd(), 'temp/wm', hash_name + '.png')
            file_wm.save(wm_path)
            g.file_list.append(wm_path)

            # 保存ppt中所有图片
            pic_path = os.path.join(os.getcwd(), 'temp/picture/', hash_name)
            if not os.path.exists(pic_path):
                os.mkdir(pic_path)
                g.path_list.append(pic_path)
            name_list = savePic.save_pic(ppt_path_name, pic_path)

            # 添加盲水印
            for name in name_list:
                name_path = os.path.join(pic_path, name)
                enPic.en_pic(name_path, wm_path)

            # 还原图片
            infos = infoPic.InfoPic(ppt_path_name)
            replacePic.replace_pic(ppt_path_name, pic_path, infos.get_info())

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(wm_path)
                    shutil.rmtree(pic_path)
                    os.remove(ppt_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的PPT文件下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/ppt'), ppt_name, as_attachment=True)
        else:
            flash("请上传PPTX文件与PNG格式水印图片！")
            return render_template('main/selfwm_add.html')
    return render_template('main/selfwm_add.html')


# 图片水印添加——生成盲水印
@main.route('/genpic_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def genpic_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/genpic_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 img:原图 wm_text：水印字样
        img = request.files['img']
        wm_text = request.form.get('wm_text')

        # 验证水印内容
        if len(wm_text) == 0:
            flash("水印内容不能为空！")
            return render_template('main/genpic_add.html')

        # 验证获取的img文件
        if img and formVerify.allowed_file_img(img.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            img_hashname = hashlib.md5(SECRET_KEY + img.filename + current_user.email).hexdigest()
            # 保存img
            imgname = img_hashname + '.' + img.filename.rsplit('.', 1)[1]
            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            img.save(img_path_name)
            g.file_list.append(img_path_name)

            # 生成水印
            wm_path = os.path.join(os.getcwd(), 'temp/wm')
            wm_file = genWm.gen_wm(wm_text, img_hashname, wm_path)
            g.file_list.append(wm_file)

            # 添加水印
            enPic.en_pic(img_path_name, wm_file)

            # 更新img文件名（在en_pic处理后，img文件统一为PNG格式）
            imgname = imgname[:-4] + '.png'
            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            g.file_list[0] = img_path_name

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(img_path_name)
                    os.remove(wm_file)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的图片下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/picture/'), imgname, as_attachment=True)
        else:
            flash("请上传JPG，PNG格式图片！")
            return render_template('main/genpic_add.html')
    return render_template('main/genpic_add.html')


# 图片水印添加——生成传统水印
@main.route('/compic_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def compic_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/compic_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 img:原图 wm_text：水印字样
        img = request.files['img']
        wm_text = request.form.get('wm_text')

        # 验证水印内容
        if len(wm_text) == 0:
            flash("水印内容不能为空！")
            return render_template('main/compic_add.html')

        # 验证获取的img文件
        if img and formVerify.allowed_file_img(img.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            img_hashname = hashlib.md5(SECRET_KEY + img.filename + current_user.email).hexdigest()
            # 保存img
            imgname = img_hashname + '.' + img.filename.rsplit('.', 1)[1]
            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            img.save(img_path_name)
            g.file_list.append(img_path_name)

            # 添加传统水印(com_wm中包含生成传统水印内容)
            comWm.com_wm(img_path_name, wm_text)

            # 更新img文件名（在en_pic处理后，img文件统一为PNG格式）
            imgname = imgname[:-4] + '.png'
            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            g.file_list[0] = img_path_name

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(img_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的图片下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/picture/'), imgname, as_attachment=True)
        else:
            flash("请上传JPG，PNG格式图片！")
            return render_template('main/compic_add.html')
    return render_template('main/compic_add.html')


# 图片水印添加——上传水印图
@main.route('/selfpic_add', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def selfpic_add():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/selfpic_add.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 img:原图 file_wm：水印图
        img = request.files['img']
        file_wm = request.files['file_wm']

        # 验证获取的img文件和水印图
        if img and file_wm and formVerify.allowed_file_img(img.filename) and formVerify.allowed_file_png(
                file_wm.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            img_hashname = hashlib.md5(SECRET_KEY + img.filename + current_user.email).hexdigest()
            # 保存img
            imgname = img_hashname + '.' + img.filename.rsplit('.', 1)[1]
            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            img.save(img_path_name)
            g.file_list.append(img_path_name)

            # 保存水印
            wm_path_name = os.path.join(os.getcwd(), 'temp/wm', img_hashname + '.png')
            file_wm.save(wm_path_name)
            g.file_list.append(wm_path_name)

            # 添加水印
            enPic.en_pic(img_path_name, wm_path_name)

            # 更新img文件名（在en_pic处理后，img文件统一为PNG格式）
            imgname = imgname[:-4] + '.png'
            img_path_name = os.path.join(os.getcwd(), 'temp/picture', imgname)
            g.file_list[0] = img_path_name

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(img_path_name)
                    os.remove(wm_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的图片下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/picture'), imgname, as_attachment=True)
        else:
            flash("请上传JPG，PNG格式原图与PNG格式水印图片！")
            return render_template('main/selfpic_add.html')
    return render_template('main/selfpic_add.html')


# 水印提取——提取ppt水印
@main.route('/wm_ppt_withdraw', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def wm_ppt_withdraw():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/wm_ppt_withdraw.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 ppt1:添加过水印的ppt ppt2：原ppt page1：ppt1所用页码 page2：ppt2所用页码
        ppt1 = request.files['ppt1']
        ppt2 = request.files['ppt2']
        page1 = request.form.get('page1')
        page2 = request.form.get('page2')

        # 验证获取的ppt文件和page页码（是否为数字）
        if ppt1 and ppt2 and formVerify.allowed_file_ppt(ppt1.filename) and formVerify.allowed_file_ppt(
                ppt2.filename) and formVerify.allowed_text_num(page1) and formVerify.allowed_text_num(page2):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            ppt1_hashname = hashlib.md5(SECRET_KEY + ppt1.filename + current_user.email).hexdigest()
            ppt2_hashname = hashlib.md5(SECRET_KEY + ppt2.filename + current_user.email).hexdigest()
            if ppt1_hashname == ppt2_hashname:
                ppt2_hashname = ppt2_hashname + '1'

            res_hashname = hashlib.md5(SECRET_KEY + current_user.email).hexdigest()

            # 保存ppt1，ppt2
            ppt1name = ppt1_hashname + '.pptx'
            ppt2name = ppt2_hashname + '.pptx'
            ppt1_path_name = os.path.join(os.getcwd(), 'temp/ppt/', ppt1name)
            ppt2_path_name = os.path.join(os.getcwd(), 'temp/ppt/', ppt2name)
            ppt1.save(ppt1_path_name)
            g.file_list.append(ppt1_path_name)
            ppt2.save(ppt2_path_name)
            g.file_list.append(ppt2_path_name)

            # 生成压缩文件目录（如果ppt中有有效图片则通过zip文件返回下载）
            zip_path = os.path.join(os.getcwd(), 'temp/zip/')
            zip_name = res_hashname + '.zip'
            zip_path_name = os.path.join(zip_path, zip_name)

            # ppt1图片目录
            pic1_path = os.path.join(os.getcwd(), 'temp/picture/', ppt1_hashname)
            if not os.path.exists(pic1_path):
                os.mkdir(pic1_path)
                g.path_list.append(pic1_path)

            # ppt2图片目录
            pic2_path = os.path.join(os.getcwd(), 'temp/picture/', ppt2_hashname)
            if not os.path.exists(pic2_path):
                os.mkdir(pic2_path)
                g.path_list.append(pic2_path)

            # res结果图片目录
            res_path = os.path.join(os.getcwd(), 'temp/picture/', res_hashname)
            if not os.path.exists(res_path):
                os.mkdir(res_path)
                g.path_list.append(res_path)

            # ppt信息dict（用于传入提取函数）
            file_info = {'ppt1_path_name': ppt1_path_name, 'ppt2_path_name': ppt2_path_name, 'ppt1_page': int(page1),
                         'ppt2_page': int(page2), 'pic1_path': pic1_path, 'pic2_path': pic2_path}

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    shutil.rmtree(pic1_path)
                    shutil.rmtree(pic2_path)
                    shutil.rmtree(res_path)

                    os.remove(ppt1_path_name)
                    os.remove(ppt2_path_name)
                    os.remove(zip_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 验证ppt对应page页码是否有效(page页码小于Slide数目)
            if not formVerify.allowed_page_num(file_info):
                flash("请输入有效页码！")
                return render_template('main/wm_ppt_withdraw.html')

            # 提取图片并返回图片信息name1_list，name2_list
            name1_list, name2_list = withdrawPic.withdraw_pic(file_info)

            # 提取图片数为0或图片数目不相等，则无效
            if name1_list.__len__() == 0 or name1_list.__len__() != name2_list.__len__():
                flash("PPT图片数目无效！建议使用图片对比！")
                return render_template('main/wm_ppt_withdraw.html')

            # 批量提取水印图
            for i in range(name1_list.__len__()):
                name1_path_name = os.path.join(pic1_path, name1_list[i])
                name2_path_name = os.path.join(pic2_path, name2_list[i])
                res_path_name = os.path.join(res_path, name1_list[i])
                # 提取水印
                de_result = dePic.de_pic(name1_path_name, name2_path_name, res_path_name)
                # 如果图片大小不对应则无效
                if de_result:
                    flash("图片尺寸不正确，无法提取！")
                    return render_template('main/wm_ppt_withdraw.html')

            # 将水印图打包
            zipPic.zip_pic(res_path, zip_path_name)
            g.file_list.append(zip_path_name)

            # 返回处理完成后的ZIP文件下载
            return send_from_directory(zip_path, zip_name, as_attachment=True)
        else:
            flash("请上传PPTX文件！")
            return render_template('main/wm_ppt_withdraw.html')
    return render_template('main/wm_ppt_withdraw.html')


# 水印提取——提取图片水印
@main.route('/wm_img_withdraw', methods=['GET', 'POST'])
@login_required
@formVerify.error_decorator
def wm_img_withdraw():
    if request.method == 'POST':
        # 保存request信息
        g.url = 'main/wm_ppt_withdraw.html'
        g.file_list = []
        g.path_list = []

        # 获取表单文件 img:添加过水印的图 ori：原图
        img = request.files['img']
        ori = request.files['ori']

        # 验证获取的img，ori文件
        if img and ori and formVerify.allowed_file_img(img.filename) and formVerify.allowed_file_img(ori.filename):
            # 文件名hash处理
            SECRET_KEY = unicode(current_app.config.get('SECRET_KEY'), 'utf-8')
            img_hashname = hashlib.md5(SECRET_KEY + img.filename + current_user.email).hexdigest()
            ori_hashname = hashlib.md5(SECRET_KEY + ori.filename + current_user.email).hexdigest()
            if img_hashname == ori_hashname:
                ori_hashname = ori_hashname + '1'

            imgname = img_hashname + '.' + img.filename.rsplit('.', 1)[1]
            oriname = ori_hashname + '.' + ori.filename.rsplit('.', 1)[1]
            resname = hashlib.md5(SECRET_KEY + current_user.email).hexdigest() + '.png'

            img_path_name = os.path.join(os.getcwd(), 'temp/picture/', imgname)
            ori_path_name = os.path.join(os.getcwd(), 'temp/picture/', oriname)
            res_path_name = os.path.join(os.getcwd(), 'temp/picture/', resname)

            # 保存img,ori
            img.save(img_path_name)
            g.file_list.append(img_path_name)
            ori.save(ori_path_name)
            g.file_list.append(ori_path_name)

            # 提取水印
            de_result = dePic.de_pic(img_path_name, ori_path_name, res_path_name)
            g.file_list.append(res_path_name)
            # 如果图片大小不对应则无效
            if de_result:
                flash("图片尺寸不正确，无法提取！")
                return render_template('main/wm_img_withdraw.html')

            # request后删除产生的临时文件
            @after_this_request
            def remove_file(response):
                try:
                    os.remove(img_path_name)
                    os.remove(ori_path_name)
                    os.remove(res_path_name)
                except Exception as error:
                    current_app.logger.error("Error removing or closing downloaded file handle", error)
                return response

            # 返回处理完成后的图片下载
            return send_from_directory(os.path.join(os.getcwd(), 'temp/picture'), resname, as_attachment=True)

        else:
            flash("请上传JPG与PNG格式图片！")
            return render_template('main/wm_img_withdraw.html')
    return render_template('main/wm_img_withdraw.html')
